package priv.mill.graph.topo;

/**
 * 有向图的topo排序
 */
public class TopoApp {
    public static void main(String[] args) {
        Graph graph = new Graph();
        graph.addVertex('A');
        graph.addVertex('B');
        graph.addVertex('C');
        graph.addVertex('D');
        graph.addVertex('E');
        graph.addVertex('F');
        graph.addVertex('G');
        graph.addVertex('H');

        graph.addEdge(0, 3);
        graph.addEdge(0, 4);
        graph.addEdge(1, 4);
        graph.addEdge(2, 5);
        graph.addEdge(3, 6);
        graph.addEdge(4, 6);
        graph.addEdge(5, 7);
        graph.addEdge(6, 7);

        graph.topo();

//        B A E D G C F H
    }
}

class Vertex {

    public char label;

    public Vertex(char label) {
        this.label = label;
    }
}

class Graph {

    private static final int MAX_SIZE = 20;
    private Vertex[] vertexList;
    private int adjMat[][];
    private int nVerts;
    private char sortedArray[];

    public Graph() {
        vertexList = new Vertex[MAX_SIZE];
        adjMat = new int[MAX_SIZE][MAX_SIZE];
        sortedArray = new char[MAX_SIZE];
    }

    public void topo() {
        int idx = nVerts;
        while (nVerts > 0) {
            int currentVertex = nosuccessors();
            if (currentVertex == -1) {
                System.err.println("不是无环图");
                return;
            } else {
                sortedArray[nVerts - 1] = vertexList[currentVertex].label;
                deleteVertex(currentVertex);
            }
        }
        for (int i = 0; i < idx; i++) {
            System.out.println(sortedArray[i] + " ");
        }
    }

    private void deleteVertex(int currentVertex) {

        if (currentVertex != nVerts - 1) {//最后一个可直接覆盖
            for (int i = currentVertex; i < nVerts - 1; i++) {
                vertexList[i] = vertexList[i + 1];
            }
            for (int row = currentVertex; row < nVerts - 1; row++) {
                for (int c = 0; c < nVerts; c++) {
                    adjMat[row][c] = adjMat[row + 1][c];
                }
            }
            for (int col = currentVertex; col < nVerts - 1; col++) {
                for (int r = 0; r < nVerts - 1; r++) {
                    adjMat[r][col] = adjMat[r][col + 1];
                }
            }
        }
        nVerts--;
    }

    /**
     * 从顶点0开始找依赖别人的排在最后面
     *
     * @return
     */
    private int nosuccessors() {
        for (int row = 0; row < nVerts; row++) {
            int col;
            for (col = 0; col < nVerts; col++) {
                if (adjMat[row][col] == 1) {
                    break;
                }
            }
            if (col == nVerts) {
                return row;
            }
        }
        return -1;
    }

    public void addEdge(int start, int end) {
        adjMat[start][end] = 1;
    }

    public void addVertex(char laben) {
        vertexList[nVerts++] = new Vertex(laben);
    }
}

